package org.jsola.hr.service.impl;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateUtils;
import org.jsola.core.Page;
import org.jsola.hr.common.ExampleKit;
import org.jsola.hr.common.HrKit;
import org.jsola.hr.constant.ExtraType;
import org.jsola.hr.constant.HrConstants;
import org.jsola.hr.dao.IAttendPunchTimeDAO;
import org.jsola.hr.dto.AttendPunchTimeAddDTO;
import org.jsola.hr.dto.AttendPunchTimeUpdateDTO;
import org.jsola.hr.dto.attendrule.AttendRulePunchTimeAddDTO;
import org.jsola.hr.dto.attendrule.NeedPunchDateAddDTO;
import org.jsola.hr.dto.attendschedule.AttendPeriodDTO;
import org.jsola.hr.entity.AttendExtraJsonDO;
import org.jsola.hr.entity.AttendPlanDO;
import org.jsola.hr.entity.AttendPunchRecordDO;
import org.jsola.hr.entity.AttendPunchTimeDO;
import org.jsola.hr.query.AttendPunchRecordQuery;
import org.jsola.hr.query.AttendPunchTimeQuery;
import org.jsola.hr.service.IAttendExtraJsonService;
import org.jsola.hr.service.IAttendPlanService;
import org.jsola.hr.service.IAttendPunchRecordService;
import org.jsola.hr.service.IAttendPunchTimeService;
import org.jsola.hr.vo.AttendPointTimeVO;
import org.jsola.hr.vo.AttendPunchTimeListVO;
import org.jsola.hr.vo.AttendPunchTimeVO;
import org.jsola.user.core.TokenUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author zhr
 */
@Slf4j
@Service("hrAttendPunchTimeServiceImpl")
public class AttendPunchTimeServiceImpl implements IAttendPunchTimeService {

    @Autowired
    private IAttendPunchTimeDAO attendPunchTimeDAO;
    @Autowired
    private IAttendPlanService attendPlanService;
    @Autowired
    private IAttendPunchRecordService attendPunchRecordService;
    @Autowired
    private IAttendExtraJsonService attendExtraJsonService;

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public AttendPunchTimeVO save(AttendPunchTimeAddDTO attendPunchTimeAddDTO, TokenUser tokenUser) {
        // 转DO
        AttendPunchTimeDO attendPunchTimeDO = attendPunchTimeAddDTO.to(AttendPunchTimeDO.class);
        // 保存
        attendPunchTimeDO = save(attendPunchTimeDO, tokenUser.getSiteId(), tokenUser.getUserId());
        return attendPunchTimeDO.to(AttendPunchTimeVO.class);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int update(AttendPunchTimeUpdateDTO attendPunchTimeUpdateDTO, TokenUser tokenUser) {
        //转DO
        AttendPunchTimeDO attendPunchTimeDO = attendPunchTimeUpdateDTO.to(AttendPunchTimeDO.class);
        //根据主键更新，只更新非null值
        return updateByIdSelective(attendPunchTimeDO, tokenUser.getSiteId(), tokenUser.getUserId());
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int deleteByIds(TokenUser tokenUser, String... attendPunchTimeIds) {
        return logicalDeleteByIds(tokenUser.getSiteId(), tokenUser.getUserId(), (Object[]) attendPunchTimeIds);
    }


    @Override
    public AttendPunchTimeVO selectById(String attendPunchTimeId, String siteId) {
        AttendPunchTimeDO attendPunchTimeDO = selectDOById(attendPunchTimeId, siteId);
        if (attendPunchTimeDO == null) {
            return null;
        }
        return attendPunchTimeDO.to(AttendPunchTimeVO.class);
    }

    @Override
    public List<AttendPunchTimeListVO> select(AttendPunchTimeQuery attendPunchTimeQuery, String siteId) {
        List<AttendPunchTimeDO> attendPunchTimeDOList = selectDO(attendPunchTimeQuery, siteId);
        if(CollectionUtils.isEmpty(attendPunchTimeDOList)) {
            return attendPunchTimeDOList == null ? null : new ArrayList<>();
        }
        return attendPunchTimeDOList.stream()
                .map(attendPunchTimeDO -> attendPunchTimeDO.to(AttendPunchTimeListVO.class))
                .collect(Collectors.toList());
    }

    @Override
    public int selectCount(AttendPunchTimeQuery attendPunchTimeQuery, String siteId) {
        Example example = buildExample(attendPunchTimeQuery,siteId);
        return attendPunchTimeDAO.selectCountByExample(example);
    }

    @Override
    public Page<AttendPunchTimeListVO> selectPage(AttendPunchTimeQuery attendPunchTimeQuery, String siteId) {
        Example example = buildExample(attendPunchTimeQuery,siteId);
        Page<AttendPunchTimeDO> page = attendPunchTimeDAO.selectPageByExample(example,
                attendPunchTimeQuery.getPageNo(),
                attendPunchTimeQuery.getPageSize());

        return page.to(AttendPunchTimeListVO.class);
    }

    @Override
    public AttendPunchTimeDO selectDOById(String attendPunchTimeId, String siteId) {
        return listById(attendPunchTimeId, siteId);
    }

    @Override
    public List<AttendPunchTimeDO> selectDO(AttendPunchTimeQuery attendPunchTimeQuery, String siteId) {
        Example example = buildExample(attendPunchTimeQuery,siteId);
        return attendPunchTimeDAO.selectByExample(example);
    }

    @Override
    public List<AttendPunchTimeDO> selectDOByAttendPlanId(String attendPlanId, String siteId) {
        Example example = new Example(AttendPunchTimeDO.class);
        example.and()
                .andEqualTo("siteId", siteId)
                .andLike("attendPlanId", "%" + attendPlanId + "%");
        return attendPunchTimeDAO.selectByExample(example);
    }

    @Override
    public int deleteByAttendPlanId(String attendPlanId, String siteId) {
        AttendPunchTimeQuery attendPunchTimeQuery = new AttendPunchTimeQuery();
        attendPunchTimeQuery.setAttendPlanId(attendPlanId);
        Example example = buildExample(attendPunchTimeQuery,siteId);
        return attendPunchTimeDAO.deleteByExample(example);
    }


    /**
     * 固定上下班的打卡时间
     *
     * @param attendPlanId 考勤规则ID
     * @param attendDateStr 考勤日期
     * @param tokenUser 当前用户
     * @return
     */
    @Override
    public AttendRulePunchTimeAddDTO puncheTimeForFixed(String attendPlanId, String attendDateStr, TokenUser tokenUser) {

        log.info("查询当前的打卡日期("+ attendDateStr +")是否在考勤时间范围内");
        Date attendDate = null;
        try {
            attendDate = DateUtils.parseDate(attendDateStr, "yyyy-MM-dd");
        } catch (ParseException e) {
            e.printStackTrace();
        }

        AttendRulePunchTimeAddDTO attendRulePunchTimeAddDTO = null;

        // 根据考勤规则ID查询考勤打卡时间(hr_attend_punch_time)
        AttendPunchTimeQuery attendPunchTimeQuery = new AttendPunchTimeQuery();
        attendPunchTimeQuery.setAttendPlanId(attendPlanId);
        List<AttendPunchTimeDO> attendPunchTimeList = this.selectDO(attendPunchTimeQuery, tokenUser.getSiteId());
        if (org.apache.commons.collections.CollectionUtils.isEmpty(attendPunchTimeList)) {
            return null;
        }

        for (AttendPunchTimeDO attendPunchTime : attendPunchTimeList) {
            // 查询今天是星期几
            String todayWeek = HrKit.getWeek(attendDate);
            log.info("查询今天是星期几: " + todayWeek);
            boolean flag = false;
            // 工作周
            List<String> workWeekList = JSON.parseArray(attendPunchTime.getWorkWeekJson(), String.class);
            log.info("工勤工作周: " + JSON.toJSONString(workWeekList));
            if (workWeekList == null || workWeekList.size() <= 0) {
                continue;
            }
            for (String workWeek : workWeekList) {
                if (workWeek.equals(todayWeek)) {

                    attendRulePunchTimeAddDTO = attendPunchTime.to(AttendRulePunchTimeAddDTO.class);
                    attendRulePunchTimeAddDTO.setWorkWeekList(workWeekList);
                    attendRulePunchTimeAddDTO.setPeriodList(JSON.parseArray(attendPunchTime.getPeriodJson(), AttendPeriodDTO.class));
                    attendRulePunchTimeAddDTO.setAttendPunchTimeId(attendPunchTime.getId());
                    flag = true;
                    break;
                }
                else {
                    log.info("未匹配到: 当前的匹配值:" + workWeek + " 被匹配的:" + todayWeek);
                }
            }

            if (flag) {
                break;
            }
        }

        log.info("考勤打卡时间查询结果:" + JSON.toJSONString(attendRulePunchTimeAddDTO));

        return attendRulePunchTimeAddDTO;
    }

    /**
     * 自由上下班
     *
     * @param attendPlanId
     * @param tokenUser
     * @return
     */
    @Override
    public List<String> getFreeWork(String attendPlanId, String attendDateStr, TokenUser tokenUser) {
        log.info("自由上下班-查询工作周");
        Date attendDate = null;
        try {
            attendDate = DateUtils.parseDate(attendDateStr, "yyyy-MM-dd");
        } catch (ParseException e) {
            e.printStackTrace();
        }

        List<String> workWeekList = null;

        // 根据考勤规则ID查询考勤打卡时间(hr_attend_punch_time)
        AttendPunchTimeQuery attendPunchTimeQuery = new AttendPunchTimeQuery();
        attendPunchTimeQuery.setAttendPlanId(attendPlanId);
        List<AttendPunchTimeDO> attendPunchTimeList = this.selectDO(attendPunchTimeQuery, tokenUser.getSiteId());
        log.info("自由上下班-查询到的所有打卡时间attendPunchTimeList:" + JSON.toJSONString(attendPunchTimeList));
        if (attendPunchTimeList.size() <= 0) {
            return null;
        }

        for (AttendPunchTimeDO attendPunchTime : attendPunchTimeList) {
            // 查询今天是星期几
            String todayWeek = HrKit.getWeek(attendDate);
            boolean flag = false;
            // 工作周
            workWeekList = JSON.parseArray(attendPunchTime.getWorkWeekJson(), String.class);
            if (workWeekList == null || workWeekList.size() <= 0) {
                continue;
            }
            for (String workWeek : workWeekList) {
                if (workWeek.equals(todayWeek)) {
                    flag = true;
                    break;
                }
                else {
                    log.info("未匹配到: 当前的匹配值:" + workWeek + " 被匹配的:" + todayWeek);
                }
            }

            if (flag) {
                break;
            }
        }

        log.info("自由上下班-查询工作周-结果-workWeekList:" + JSON.toJSONString(workWeekList));

        return workWeekList;
    }

    /**
     * 查询当前日期是否工作日，如果为空不是，不为空则是
     *
     * @param attendPlanId 考勤规则ID
     * @param attendDateStr 考勤日期
     * @param siteId 站点ID
     * @return
     */
    @Override
    public AttendRulePunchTimeAddDTO selectOnWorkTime(String attendPlanId, String attendDateStr, String siteId) {

        AttendRulePunchTimeAddDTO attendPunchTime = null;

        Date attendDate = null;
        try {
            attendDate = DateUtils.parseDate(attendDateStr, "yyyy-MM-dd");
        } catch (ParseException e) {
            e.printStackTrace();
        }

        String week = HrKit.getWeek(attendDate);

        AttendPunchTimeQuery attendPunchTimeQuery = new AttendPunchTimeQuery();
        attendPunchTimeQuery.setAttendPlanId(attendPlanId);

        List<AttendPunchTimeDO> attendPunchTimeDOList = this.selectDO(attendPunchTimeQuery, siteId);
        if (attendPunchTimeDOList.size() > 0) {
            for (AttendPunchTimeDO attendPunchTimeDO : attendPunchTimeDOList) {
                List<AttendRulePunchTimeAddDTO> punchTimeList = JSON.parseArray(attendPunchTimeDO.getWorkWeekJson(), AttendRulePunchTimeAddDTO.class);
                if (punchTimeList != null && punchTimeList.size() > 0) {
                    for (AttendRulePunchTimeAddDTO attendRulePunchTimeAddDTO : punchTimeList) {
                        List<String> workWeekList = attendRulePunchTimeAddDTO.getWorkWeekList();
                        if (workWeekList != null && workWeekList.size() > 0) {
                            for (String workWeek : workWeekList) {
                                if (workWeek.equals(week)) {
                                    attendPunchTime = attendRulePunchTimeAddDTO;
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }

        return attendPunchTime;
    }

    @Override
    public int logicDelByAttendPlanId(String attendPlanId, TokenUser tokenUser) {

        // 根据考勤规则ID查询
        AttendPunchTimeQuery attendPunchTimeQuery = new AttendPunchTimeQuery();
        attendPunchTimeQuery.setAttendPlanId(attendPlanId);
        List<AttendPunchTimeDO> dataList = this.selectDO(attendPunchTimeQuery, tokenUser.getSiteId());
        if (dataList.size() <= 0) {
            return 0;
        }

        for (AttendPunchTimeDO attendPunchTime : dataList) {

            AttendPunchTimeDO attendPunchTimeDO = new AttendPunchTimeDO();
            attendPunchTimeDO.setId(attendPunchTime.getId());
            attendPunchTimeDO.setValid(false);
            attendPunchTimeDO.setModifiedUserId(tokenUser.getUserId());
            attendPunchTimeDO.setGmtModified(new Date());
            attendPunchTimeDAO.updateByPrimaryKeySelective(attendPunchTimeDO);
        }
        return 0;
    }

    /**
     * 当打卡时间修改了之后，重置当天的考勤记录
     * @param todayStr
     * @param attendPlanId
     * @param punchTimeList
     * @param needPunchDateList
     * @param tokenUser
     * @return
     */
    @Override
    public int resetTodayPunchRecord(String todayStr, String attendPlanId, List<AttendRulePunchTimeAddDTO> punchTimeList, List<NeedPunchDateAddDTO> needPunchDateList, TokenUser tokenUser) {

        // 根据考勤规则查询今日所使用的打卡时间
        AttendPlanDO attendPlanDO = attendPlanService.selectDOById(attendPlanId, tokenUser.getSiteId());

        // 新修改的打卡时段
        List<AttendPeriodDTO> periodNewList = null;
        //
        List<AttendPeriodDTO> periodOldList = null;

        // 如果是固定上下班
        if (attendPlanDO.getPlanType() == 1) {
            // 查询当天使用的打卡时段
            for (AttendRulePunchTimeAddDTO attendPunchTime : punchTimeList) {
                // 查询今天是星期几
                String todayWeek = null;
                try {
                    todayWeek = HrKit.getWeek(DateUtils.parseDate(todayStr, "yyyy-MM-dd"));
                } catch (ParseException e) {
                    e.printStackTrace();
                }
                boolean flag = false;
                // 工作周
                List<String> workWeekList = attendPunchTime.getWorkWeekList();
                if (workWeekList == null || workWeekList.size() <= 0) {
                    continue;
                }
                for (String workWeek : workWeekList) {
                    if (workWeek.equals(todayWeek)) {
                        periodNewList = attendPunchTime.getPeriodList();
                        flag = true;
                        break;
                    }
                }

                if (flag) {
                    break;
                }
            }

            AttendRulePunchTimeAddDTO attendRulePunchTimeAddDTO = this.puncheTimeForFixed(attendPlanId, todayStr, tokenUser);
            if (attendRulePunchTimeAddDTO != null) {
                periodOldList = attendRulePunchTimeAddDTO.getPeriodList();
            }
        }
        // 如果是按班次
        if (attendPlanDO.getPlanType() == 2) {





        }

        // 所有的打卡记录
        List<AttendPunchRecordDO> allPunchRecordList = new ArrayList<>();

        // 旧版本的时间点
        List<AttendPointTimeVO> pointTimeOldList = new ArrayList<>();

        // 根据打卡时间段的时间点，查询当前的所有的打卡记录
        if (periodOldList != null && periodOldList.size() > 0) {

            periodOldList.sort(Comparator.comparingInt(AttendPeriodDTO::getSort));

            for (AttendPeriodDTO attendPeriod : periodOldList) {

                if (attendPeriod.getType() == 2) {
                    continue;
                }

                AttendPointTimeVO point1 = new AttendPointTimeVO();
                point1.setPointTime(attendPeriod.getStartPeriod());
                point1.setType(attendPeriod.getType());
                pointTimeOldList.add(point1);

                AttendPointTimeVO point2 = new AttendPointTimeVO();
                point2.setPointTime(attendPeriod.getStartPeriod());
                point2.setType(attendPeriod.getType());
                pointTimeOldList.add(point2);
            }
        }

        // 新版本的打卡时间点
        List<AttendPointTimeVO> pointTimeNewList = new ArrayList<>();

        if (periodNewList != null && periodNewList.size() > 0) {

            periodNewList.sort(Comparator.comparingInt(AttendPeriodDTO::getSort));

            for (AttendPeriodDTO attendPeriod : periodNewList) {

                if (attendPeriod.getType() == 2) {
                    continue;
                }

                AttendPointTimeVO point1 = new AttendPointTimeVO();
                point1.setPointTime(attendPeriod.getStartPeriod());
                point1.setType(attendPeriod.getType());
                pointTimeNewList.add(point1);

                AttendPointTimeVO point2 = new AttendPointTimeVO();
                point2.setPointTime(attendPeriod.getStartPeriod());
                point2.setType(attendPeriod.getType());
                pointTimeNewList.add(point2);
            }
        }

        // 查询当天所有的打卡记录
        AttendPunchRecordQuery attendPunchRecordQuery = new AttendPunchRecordQuery();
        attendPunchRecordQuery.setAttendPlanId(attendPlanId);
        attendPunchRecordQuery.setYear(todayStr.split("-")[0]);
        attendPunchRecordQuery.setMonth(todayStr.split("-")[1]);
        attendPunchRecordQuery.setDay(todayStr.split("-")[2]);
        List<AttendPunchRecordDO> attendPunchRecordList = attendPunchRecordService.selectDO(attendPunchRecordQuery, tokenUser.getSiteId());

        int oldSize = pointTimeOldList.size();
        int newSize = pointTimeNewList.size();

        int index = 0;
        if (oldSize > newSize) {
            index = newSize;
        }
        else if (newSize > oldSize){
            index = oldSize;
        }
        else {
            index = oldSize;
        }

        for (int i = 0; i < index; i++) {

            AttendPointTimeVO oldPoint = pointTimeOldList.get(i);
            AttendPointTimeVO newPoint = pointTimeNewList.get(i);

            String newPointTimeStr = newPoint.getPointTime();
            String oldPointTimeStr = oldPoint.getPointTime();
            int newPointTimeInt = Integer.valueOf(newPointTimeStr.replace(":", "")).intValue();
            int oldPointTimeInt = Integer.valueOf(oldPointTimeStr.replace(":", "")).intValue();
            int pointType = newPoint.getType();

            if (oldPoint.getPointTime().equals(newPoint.getPointTime())) {
                continue;
            }

            List<AttendPunchRecordDO> oldRecordList = new ArrayList<>();
            // 旧的打卡时间点不等于新的打卡时间点，以新的打卡时间点为准
            // 过滤所有的旧的点卡时间点
            if (attendPunchRecordList != null && attendPunchRecordList.size() > 0) {
                for (AttendPunchRecordDO attendPunchRecord : attendPunchRecordList) {

                    if (attendPunchRecord.getStandardTime().equals(oldPoint)) {
                        oldRecordList.add(attendPunchRecord);
                    }
                }
            }

            // 以新的打卡时间点为准
            if (oldRecordList != null && oldRecordList.size() > 0) {
                for (AttendPunchRecordDO attendPunchRecord : oldRecordList) {

                    int punchTimeInt = 0;
//                    if (StringUtils.isNotBlank(attendPunchRecord.getPunchTime())) {
//                        punchTimeInt = Integer.valueOf(attendPunchRecord.getPunchTime().replace(":", "")).intValue();
//                    }

                    // 如果是上班
                    if (pointType == 1) {
                        // 如果新的上班时间大于旧的上班打卡时间，则状态是正常
                        if (newPointTimeInt > punchTimeInt) {
                            AttendPunchRecordDO record = new AttendPunchRecordDO();

                            record.setId(attendPunchRecord.getId());
                            // 新的考勤时间
//                            record.setStandardTime(newPointTimeStr);
                            // 原先的考勤时间
                            record.setPunchTime(attendPunchRecord.getPunchTime());
                            // 新的考勤状态 - 正常
                            record.setPunchStatus(1);
//                            record.setHisStandardTime(attendPunchRecord.getStandardTime());
                            record.setHisPunchTime(attendPunchRecord.getPunchTime());
//                            record.setHisStandardTime(attendPunchRecord.getStandardTime());

                            attendPunchRecordService.updateByIdSelective(record, tokenUser.getSiteId(), tokenUser.getUserId());
                        }
                        else {
                            AttendPunchRecordDO record = new AttendPunchRecordDO();

                            record.setId(attendPunchRecord.getId());
                            // 新的考勤时间
//                            record.setStandardTime(newPointTimeStr);
                            // 原先的考勤时间
                            record.setPunchTime(attendPunchRecord.getPunchTime());
                            // 新的考勤状态 - 异常
                            record.setPunchStatus(6);
//                            record.setHisStandardTime(attendPunchRecord.getStandardTime());
                            record.setHisPunchTime(attendPunchRecord.getPunchTime());
//                            record.setHisStandardTime(attendPunchRecord.getStandardTime());

                            attendPunchRecordService.updateByIdSelective(record, tokenUser.getSiteId(), tokenUser.getUserId());
                        }

                    }
                    // 如果是下班
                    else if (pointType == 2) {
                        // 如果新的考勤时间小于打卡时间 ，正常
                        if (newPointTimeInt < punchTimeInt) {
                            AttendPunchRecordDO record = new AttendPunchRecordDO();

                            record.setId(attendPunchRecord.getId());
                            // 新的考勤时间
//                            record.setStandardTime(newPointTimeStr);
                            // 原先的考勤时间
                            record.setPunchTime(attendPunchRecord.getPunchTime());
                            // 新的考勤状态 - 正常
                            record.setPunchStatus(1);
//                            record.setHisStandardTime(attendPunchRecord.getStandardTime());
                            record.setHisPunchTime(attendPunchRecord.getPunchTime());
//                            record.setHisStandardTime(attendPunchRecord.getStandardTime());

                            attendPunchRecordService.updateByIdSelective(record, tokenUser.getSiteId(), tokenUser.getUserId());
                        }
                        else {
                            AttendPunchRecordDO record = new AttendPunchRecordDO();

                            record.setId(attendPunchRecord.getId());
                            // 新的考勤时间
//                            record.setStandardTime(newPointTimeStr);
                            // 原先的考勤时间
                            record.setPunchTime(attendPunchRecord.getPunchTime());
                            // 新的考勤状态 - 异常
                            record.setPunchStatus(6);
//                            record.setHisStandardTime(attendPunchRecord.getStandardTime());
                            record.setHisPunchTime(attendPunchRecord.getPunchTime());
//                            record.setHisStandardTime(attendPunchRecord.getStandardTime());

                            attendPunchRecordService.updateByIdSelective(record, tokenUser.getSiteId(), tokenUser.getUserId());
                        }
                    }
                }
            }

        }












        // 新版本的时间点匹配就版本的时间点
        if (pointTimeOldList.size() > 0 && pointTimeNewList.size() > 0) {

            for (AttendPointTimeVO attendPointTimeNew : pointTimeNewList) {

                String newPoint = attendPointTimeNew.getPointTime();

                for (AttendPointTimeVO attendPointTimeOld : pointTimeOldList) {
                    if (newPoint.equals(attendPointTimeOld.getPointTime())) {
                        continue;
                    }





                }
            }
        }






        // 根据考勤规则，查询当日所有的考勤记录


        return 0;
    }

    /**
     * 根据查询参数，构建example

     * @param attendPunchTimeQuery 查询参数
     * @param siteId 所属站点id
     * @return example
     */
    private Example buildExample(AttendPunchTimeQuery attendPunchTimeQuery, String siteId) {
        Example example = new Example(AttendPunchTimeDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId);
        if (attendPunchTimeQuery.getAttendPlanId() != null) {
            example.and().andLike("attendPlanId", "%" + attendPunchTimeQuery.getAttendPlanId() + "%");
        }
        if (attendPunchTimeQuery.getWorkWeekJson() != null) {
            example.and().andLike("workWeekJson", "%" + attendPunchTimeQuery.getWorkWeekJson() + "%");
        }
        if (attendPunchTimeQuery.getPeriodJson() != null) {
            example.and().andLike("periodJson", "%" + attendPunchTimeQuery.getPeriodJson() + "%");
        }
        if (attendPunchTimeQuery.getIsAdvanc() != null) {
            example.and().andEqualTo("isAdvanc", attendPunchTimeQuery.getIsAdvanc());
        }
        if (attendPunchTimeQuery.getIsAllowedLateEarly() != null) {
            example.and().andEqualTo("isAllowedLateEarly", attendPunchTimeQuery.getIsAllowedLateEarly());
        }
        if (attendPunchTimeQuery.getLateMinute() != null) {
            example.and().andEqualTo("lateMinute", attendPunchTimeQuery.getLateMinute());
        }
        if (attendPunchTimeQuery.getEarlyMinute() != null) {
            example.and().andEqualTo("earlyMinute", attendPunchTimeQuery.getEarlyMinute());
        }
        if (attendPunchTimeQuery.getIsAllowLateLate() != null) {
            example.and().andEqualTo("isAllowLateLate", attendPunchTimeQuery.getIsAllowLateLate());
        }
        if (attendPunchTimeQuery.getOffWorkLateMinute() != null) {
            example.and().andEqualTo("offWorkLateMinute", attendPunchTimeQuery.getOffWorkLateMinute());
        }
        if (attendPunchTimeQuery.getOnWorkLateMinute() != null) {
            example.and().andEqualTo("onWorkLateMinute", attendPunchTimeQuery.getOnWorkLateMinute());
        }
        if (attendPunchTimeQuery.getEarliestPunchTime() != null) {
            example.and().andEqualTo("earliestPunchTime", attendPunchTimeQuery.getEarliestPunchTime());
        }
        if (attendPunchTimeQuery.getLatestOnPunchTime() != null) {
            example.and().andEqualTo("latestOnPunchTime", attendPunchTimeQuery.getLatestOnPunchTime());
        }
        if (attendPunchTimeQuery.getEarliestOffPunchTime() != null) {
            example.and().andEqualTo("earliestOffPunchTime", attendPunchTimeQuery.getEarliestOffPunchTime());
        }
        if (attendPunchTimeQuery.getLatestPunchTime() != null) {
            example.and().andEqualTo("latestPunchTime", attendPunchTimeQuery.getLatestPunchTime());
        }
        if (attendPunchTimeQuery.getAfterWorkNeedPunch() != null) {
            example.and().andEqualTo("afterWorkNeedPunch", attendPunchTimeQuery.getAfterWorkNeedPunch());
        }
        if (attendPunchTimeQuery.getCompanyId() != null) {
            example.and().andEqualTo("companyId", attendPunchTimeQuery.getCompanyId());
        }
        if (attendPunchTimeQuery.getGmtCreateStart() != null &&
                attendPunchTimeQuery.getGmtCreateEnd() != null) {
            example.and().andBetween("gmtCreate", attendPunchTimeQuery.getGmtCreateStart(),
                    attendPunchTimeQuery.getGmtCreateEnd());
        }
        if (attendPunchTimeQuery.getCreateUserId() != null) {
            example.and().andLike("createUserId", "%" + attendPunchTimeQuery.getCreateUserId() + "%");
        }
        if (attendPunchTimeQuery.getGmtModifiedStart() != null &&
                attendPunchTimeQuery.getGmtModifiedEnd() != null) {
            example.and().andBetween("gmtModified", attendPunchTimeQuery.getGmtModifiedStart(),
                    attendPunchTimeQuery.getGmtModifiedEnd());
        }
        if (attendPunchTimeQuery.getModifiedUserId() != null) {
            example.and().andLike("modifiedUserId", "%" + attendPunchTimeQuery.getModifiedUserId() + "%");
        }
        // 排序
        ExampleKit.setExampleOrder(example,attendPunchTimeQuery.getOrders());
        return example;
    }

    @Override
    public AttendRulePunchTimeAddDTO puncheTimeForSpecial(String attendPlanId, String attendDateStr, TokenUser tokenUser){
        log.info("特殊日期计算打卡时间相关");
        Date attendDate = null;
        try {
            attendDate = DateUtils.parseDate(attendDateStr, "yyyy-MM-dd");
        } catch (ParseException e) {
            e.printStackTrace();
        }

        AttendRulePunchTimeAddDTO attendRulePunchTimeAddDTO = null;

        // 根据考勤规则ID查询考勤打卡时间(hr_attend_punch_time)
        AttendPunchTimeQuery attendPunchTimeQuery = new AttendPunchTimeQuery();
        attendPunchTimeQuery.setAttendPlanId(attendPlanId);
        List<AttendPunchTimeDO> attendPunchTimeList = this.selectDO(attendPunchTimeQuery, tokenUser.getSiteId());
        if (org.apache.commons.collections.CollectionUtils.isEmpty(attendPunchTimeList)) {
            return null;
        }

        for (AttendPunchTimeDO attendPunchTime : attendPunchTimeList) {
            attendRulePunchTimeAddDTO = attendPunchTime.to(AttendRulePunchTimeAddDTO.class);
            attendRulePunchTimeAddDTO.setPeriodList(JSON.parseArray(attendPunchTime.getPeriodJson(), AttendPeriodDTO.class));
            attendRulePunchTimeAddDTO.setAttendPunchTimeId(attendPunchTime.getId());
            break;
        }

        AttendExtraJsonDO attendExtraJsonDO = attendExtraJsonService.selectByAttendPlanIdAndExtraType(attendPlanId,
                ExtraType.ATTEND_CALENDAR_NEED_PUNCH.getValue(), tokenUser);
        if (attendExtraJsonDO != null) {
            List<NeedPunchDateAddDTO> needPunchDateList = JSON.parseArray(attendExtraJsonDO.getJsonData(), NeedPunchDateAddDTO.class);
            for (NeedPunchDateAddDTO needPunchDateAddDTO : needPunchDateList) {
                if (attendDateStr.equals(needPunchDateAddDTO.getDaily())) {
                    attendRulePunchTimeAddDTO.setPeriodList(needPunchDateAddDTO.getPeriodList());
                    break;
                }
            }
        }
        log.info("考勤打卡时间查询结果:" + JSON.toJSONString(attendRulePunchTimeAddDTO));

        return attendRulePunchTimeAddDTO;
    }
}




